package com.hanserwei.han_picture.utils;

import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.ResponseFormat;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.utils.JsonUtils;
import com.hanserwei.han_picture.domain.exception.ApiException;
import com.hanserwei.han_picture.enums.ImageCategory;
import com.hanserwei.han_picture.enums.ResponseCodeEnum;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ImageTagsGenerateUtil {
    
    // 信号量控制并发数，防止AI接口被大量并发请求压垮
    private static final Semaphore AI_CALL_SEMAPHORE = new Semaphore(3);

    @Setter
    private static String apiKey;

    // 获取所有图片分类的中文名称，用于限制AI输出
    private static String getCategoriesPrompt() {
        StringBuilder sb = new StringBuilder();
        sb.append("可选的图片分类只能是以下10种之一：\n");
        for (ImageCategory category : ImageCategory.values()) {
            sb.append("- ").append(category.getChineseName()).append("\n");
        }
        return sb.toString();
    }

    public static ImageTagsAndTile getTagsAndTile(String imgUrl) {
        // 尝试获取信号量，最多等待60秒，这个视情况设置，建议设置高一点，毕竟有批量上传。太低容易调用接口失败
        boolean acquired = false;
        try {
            acquired = AI_CALL_SEMAPHORE.tryAcquire(60, TimeUnit.SECONDS);
            if (!acquired) {
                log.warn("AI接口调用超时，当前并发数过高");
                throw new ApiException(ResponseCodeEnum.SYSTEM_ERROR, "AI服务繁忙，请稍后重试");
            }
            
            return callAIService(imgUrl);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("AI接口调用被中断", e);
            throw new ApiException(ResponseCodeEnum.SYSTEM_ERROR, "AI服务调用被中断");
        } finally {
            if (acquired) {
                AI_CALL_SEMAPHORE.release();
            }
        }
    }
    
    private static ImageTagsAndTile callAIService(String imgUrl) {
        try {
            MultiModalConversation conv = new MultiModalConversation();
            String prompt = """
                    你是一名顶尖的图像分析专家，专精于图像识别与描述。我将为你提供一张图片，你需要根据图片内容，完成以下任务：
                    
                    1. **分析图片并生成一个最能代表其主题的标题。**
                       - 标题应简洁明了，概括性强。
                    
                    2. **从图片内容中选择一个最合适的分类。**
                       %s
                       - 必须从上述分类中选择一个最符合图片内容的分类。
                    
                    3. **提取并生成5个最能描述图片核心内容的标签。**
                       - 标签要求简短、精确、高相关性。
                    
                    4. **最终结果以JSON格式输出。**
                       - 请确保JSON对象中包含 `"title"`、`"category"` 和 `"tags"` 字段。
                       - `"title"` 的值为生成的标题（字符串）。
                       - `"category"` 的值为选择的分类（字符串，必须是上述10个分类之一）。
                       - `"tags"` 的值为生成的5个标签（字符串数组）。
                    
                    **示例1：**
                    **输入图片（假设为一只在草地上奔跑的金毛犬）：**
                    **返回结果：**
                    ```json
                    {
                      "title": "阳光下的金毛犬",
                      "category": "动物",
                      "tags": [
                        "金毛犬",
                        "宠物",
                        "草地",
                        "户外",
                        "奔跑"
                      ]
                    }
                    ```
                    
                    **示例2：**
                    **输入图片（假设为一碗热气腾腾的日式拉面）：**
                    **返回结果：**
                    ```json
                    {
                      "title": "美味的日式豚骨拉面",
                      "category": "物体与静物",
                      "tags": [
                        "日式拉面",
                        "美食",
                        "豚骨汤",
                        "日料",
                        "特写"
                      ]
                    }
                    ```
                    """.formatted(getCategoriesPrompt());
            
            MultiModalMessage systemMessage = MultiModalMessage.builder().role(Role.SYSTEM.getValue())
                    .content(List.of(Collections.singletonMap("text", prompt))).build();
            MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
                    .content(List.of(Collections.singletonMap("image", imgUrl))).build();
            ResponseFormat responseFormat = ResponseFormat.builder().type("json_object").build();
            MultiModalConversationParam param = MultiModalConversationParam.builder()
                    // TODO：我服了，key泄露了。
                    .apiKey(apiKey)
                    .model("qwen-vl-max-latest")
                    .messages(Arrays.asList(systemMessage, userMessage))
                    .responseFormat(responseFormat)
                    .build();
            MultiModalConversationResult result = conv.call(param);
            return JsonUtils.fromJson((String) result.getOutput().getChoices().getFirst().getMessage().getContent().getFirst().get("text"), ImageTagsAndTile.class);
        } catch (Exception e) {
            log.error("图片标签生成失败", e);
            throw new ApiException(ResponseCodeEnum.SYSTEM_ERROR, "图片标签生成失败");
        }
    }


    public record ImageTagsAndTile(String title, String category, List<String> tags) {
    }
}
